package com.soup.common.module.sys.api;

import com.google.common.collect.ImmutableMap;
import com.soup.common.constant.CommonConstant;
import com.soup.common.entity.MenuTreeNode;
import com.soup.common.entity.QueryParam;
import com.soup.common.entity.QueryRequest;
import com.soup.common.entity.ErrorCode;
import com.soup.common.entity.Result;
import com.soup.common.module.sys.entity.Role;
import com.soup.common.exception.sys.RoleOperationException;
import com.soup.common.module.sys.service.MenuService;
import com.soup.common.module.sys.service.RoleService;
import com.soup.common.module.sys.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 权限角色api
 *
 * @author zhaoyi
 */
@Slf4j
@RestController
@RequestMapping("/role")
public class RoleApi {

    @Autowired
    private UserService userService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RoleService roleService;

    /**
     * 分页查询角色权限
     *
     * @param queryParam 分页参数
     * @return 分页结果集
     */
    @GetMapping
    public Result page(@Valid QueryRequest queryParam) {
        return roleService.page(queryParam);
    }

    /**
     * 查询所有角色
     *
     * @return 所有角色列表
     */
    @GetMapping("/all")
    public List<Role> findAll() {
        return roleService.selectAll();
    }

    /**
     * 新增角色
     *
     * @param role 角色信息
     * @return 新增结果
     */
    @PostMapping
    public int add(@RequestBody @Valid Role role) {
        valid(role);
        role.setGmtCreate(new Date());
        return roleService.save(role);
    }

    /**
     * 修改角色
     *
     * @param role 修改的角色信息
     * @param roleId 待修改的角色id
     */
    @PutMapping("/{roleId}")
    public int update(@RequestBody @Valid Role role, @PathVariable Integer roleId) {
        valid(role, roleId);
        role.setId(roleId);
        return roleService.updateNotNull(role);
    }

    /**
     * 删除角色
     *
     * @param roleId 待删除的角色id
     */
    @DeleteMapping("/{roleId}")
    public int delete(@PathVariable Integer roleId) {
        Role role = roleService.selectByKey(roleId);
        if (null == role) {
            throw new RoleOperationException(ErrorCode.ROLE_NOT_FOUND);
        }
        if (userService.countbyRoleId(roleId) > 0) {
            throw new RoleOperationException(ErrorCode.ROLE_NOT_FOUND);
        }

        // 默认超级管理员无法删除
        if (role.getId() == CommonConstant.NUM_1) {
            throw new RoleOperationException(ErrorCode.ROLE_DEL_NOT_SUPPORT);
        }

        return roleService.delete(roleId);
    }

    /**
     * 设置角色菜单
     *
     * @param roleId 角色id
     * @param menuIds 菜单列表
     * @return 设置结果
     */
    @PostMapping("/{roleId}/privilege")
    public int privilege(@PathVariable Integer roleId, @RequestBody List<Integer> menuIds) {
        Role role = roleService.selectByKey(roleId);
        if (null == role) {
            throw new RoleOperationException(ErrorCode.ROLE_NOT_FOUND);
        }

        // 默认角色无法修改菜单
        if (role.getId() == CommonConstant.NUM_1) {
            throw new RoleOperationException(ErrorCode.ROLE_PRIVILEGE_NOT_SUPPORT);
        }

        // menu settings
        return menuService.setUpRolePrivilege(roleId, menuIds);
    }

    /**
     * 查询角色的权限树
     *
     * @param roleId 角色id
     */
    @GetMapping("/{roleId}/menus")
    public Map<String, List<MenuTreeNode>> roleMenu(@PathVariable Integer roleId) {
        return menuService.fetchRoleMenuTree(roleId);
    }

    private void valid(Role role) {
        // 校验角色是否已存在
        int count = roleService.countByEqual(ImmutableMap.of("name", role.getName()));
        if (count > CommonConstant.NUM_0) {
            throw new RoleOperationException(ErrorCode.ROLE_ADD_DUPLICATED);
        }
    }

    private void valid(Role role, Integer roleId) {
        QueryParam queryParam = new QueryParam(Role.class);
        QueryParam.Criteria criteria = queryParam.createCriteria();
        criteria.andEqualTo("name", role.getName().trim());
        // 更新判断是否重复
        criteria.andNotEqualTo("id", roleId);
        List<Role> roles = roleService.selectByQueryParam(queryParam);
        if (CollectionUtils.isNotEmpty(roles)) {
            throw new RoleOperationException(ErrorCode.ROLE_UPDATE_ERROR);
        }
    }
}
